/**
 * EnvironmentView.java
 * Created December 16th 2007
 *  [2008-02-15, Ryan J. Bovorasmy] Added comments (for adv. graphics report).
 */
package protovitae.ui;

import protovitae.data.*;
import java.awt.*;
import java.awt.event.*;
//JOGL includes
import javax.media.opengl.*;
import com.sun.opengl.util.*;
//import javax.media.opengl.glu.GLU;

public class EnvironmentView extends GLCanvas implements GLEventListener, MouseListener {
    private MainWindow parent = null;
    private Simulation simulation = new Simulation(this);
    private float light_position[] = {0.0f, 100.0f, 100.0f, 1.0f};
    private float light_color[] = {5.0f, 5.0f, 5.0f, 1.0f}; // Why is this like this? Values through 1.0 are too small.
    private float lmodel_ambient[] = {0.5f, 0.5f, 0.5f, 1.0f};
    int mouseX = -1;
    int mouseY = -1; //Package visibility?
    private boolean lookForHit = false;
    
    public EnvironmentView(MainWindow parent) {
        this.parent = parent;
        this.addMouseListener(this);
    }
    
    public void setSimulation (Simulation simulation) {
        this.simulation = simulation;
    }

    
    public void init(GLAutoDrawable drawable) {
        GL gl = drawable.getGL();

        gl.setSwapInterval(1);
        gl.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
        gl.glShadeModel(GL.GL_SMOOTH);

        initLighting(drawable, light_position, light_color, lmodel_ambient);
        
        gl.glHint(GL.GL_PERSPECTIVE_CORRECTION_HINT, GL.GL_NICEST);

        gl.glEnable(gl.GL_LIGHTING);
        gl.glEnable(gl.GL_LIGHT0);
        gl.glEnable(gl.GL_DEPTH_TEST);  //may need to disable if orgnaims overlap
        gl.glEnable(GL.GL_BLEND);
        gl.glBlendFunc(GL.GL_SRC_ALPHA,GL.GL_ONE);

        Animator anim = new Animator(this);
        anim.start();
        // simulation.start();
    }

    /**
     * Initialize the lighting effects.
     * @param drawable The drawable
     * @param light_position Array that represents positional light.
     * @param light_color Array that represents light color
     * @param lmodel_ambient Array that represents ambeint light.
     */
    private void initLighting(GLAutoDrawable drawable, float[] light_position, float[] light_color, float[] lmodel_ambient) {
        GL gl = drawable.getGL();

        gl.glLightfv(gl.GL_LIGHT0, gl.GL_POSITION, light_position, 0);
        gl.glLightModelfv(gl.GL_LIGHT_MODEL_AMBIENT, lmodel_ambient, 0);
        gl.glLightfv(gl.GL_LIGHT0, gl.GL_DIFFUSE, light_color, 0);
        gl.glLightfv(gl.GL_LIGHT0, gl.GL_SPECULAR, light_color, 0);
    }

    /**
     * Let's eventually get things into perspective.
     * @param drawable
     * @param x
     * @param y
     * @param width
     * @param height
     */
    public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) {
        GL gl = drawable.getGL();
        //GLU glu = new GLU();

        gl.glViewport(0, 0, width, height);
        
        gl.glMatrixMode(GL.GL_PROJECTION);
        gl.glLoadIdentity();
        //glu.gluPerspective(45.0f, (float) width / (float) height, -100f, 100.0f); 
        gl.glOrtho(-100, 100, -100, 100, -100, 100);
        gl.glMatrixMode(GL.GL_MODELVIEW);
        gl.glLoadIdentity();
    }

    /**
     * Display function.
     * @param drawable
     */
    public void display(GLAutoDrawable drawable) {
        // parent.updateTraitTree(); // This will continiously update the trait tree, but it makes using the tree virtually impossible.
        GL gl = drawable.getGL();
        gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
        gl.glLoadIdentity();
        
        simulation.draw(gl);

        if (lookForHit) {
            ConcreteOrganism hit = simulation.processSelections(gl, mouseX, mouseY);
            if (hit != null) parent.notifySelection(hit);
            lookForHit = false;
        }
        
        gl.glFlush();
        
        try{
            Thread.sleep(25); //This thing eats 100% of one CPU if we don't limit it.
        }catch(Exception e){
            
        }
    }

    /**
     * does nothing at the moment.
     * @param obj
     */
    public void setLayout(Object obj) {
        return;
    }

    /**
     * Does nothing at the moment.
     * @param drawable
     * @param modeChanged
     * @param deviceChanged
     */
    public void displayChanged(GLAutoDrawable drawable, boolean modeChanged, boolean deviceChanged) {
    }

    /**
     * Handels mouse clicks.
     * @param e
     */
    public void mouseClicked(MouseEvent e) {
        mouseX = e.getX();
        mouseY = e.getY();
        lookForHit = true;
    }

    public void mousePressed(MouseEvent e) {
    }

    public void mouseReleased(MouseEvent e) {
    }

    public void mouseEntered(MouseEvent e) {
    }

    public void mouseExited(MouseEvent e) {
    }
    
    /**
     * Returns the MainWindow that this view belongs to.
     * @return
     */
    public MainWindow getMainWindow() {
        return parent;
    }
}
